This tutorial will take you through the steps of running an exploratory factor analysis, using the DTI data collected as part of Garner & Dux (2015). You will go through exploratory data analysis and cleaning, preparing a correlation matrix, determing the number of factors, rotating the factors to increase intepretability, and computing individual scores for each factor, given their scores on the measured variables (i.e. the data we put into the factor analysis).
First we will load the libraries and source the files that we will require to do the analysis…
library(corpcor)
library(GPArotation)
library(psych)
library(ggcorrplot)
library(tidyverse)
library(cowplot)
library(GGally)
library(wesanderson)
library(nFactors)
source("../KG_data-wrangling.R")
source("../R_rainclouds.R")
library(rmarkdown) # You need this library to run this template.
library(epuRate) # Install with devtools: install_github("holtzy/epuRate", force=TRUE)and load in our data. Note that my tracts of interest are different to yours.
## Warning in (function (..., deparse.level = 1) : number of rows of result is not
## a multiple of vector length (arg 1)
First, we want to look at the data we are putting into the factor analysis, in this case the FA values for our DTI tracts of interest.
We will first check each of our variables for outliers (otherwise known as univariate outliers), we will then check for nonlinearity and heteroscedasticity, normality, multivariate outliers, and lastly, multicollinearity and singularity. We will go through each of these terms as we deal with the data.
First we want to make sure that each of our variables, i.e. each of our tracts, contain sensible data points. As we are looking at the values of each variable on its own, not in conjunction with other variables, we call this looking for univariate outliers
To get a good idea of the distributions of each variable, its a good idea to plot them in a way that provides information about the distribution of the variables as well as possible outlier values.
Below is a raincloud plot of the tract data. Each row is a tract (named on the y axes). You can see the density of each tract’s data. You are looking to see that these look roughly normally distributed. Each participant’s FA value is one dot on the plot. A boxplot laid over the top shows you the median, and the inter-quartile range. The boxplot helps you spot outliers.
ggplot(s1.data, aes(x=tract_name, y=FA, fill = tract_name, colour = tract_name)) +
geom_flat_violin(position = position_nudge(x = .25, y = 0), adjust =2, trim =
TRUE) +
geom_point(position=position_jitter(width=.15), size=.25) +
geom_boxplot(aes(x = tract_name, y = FA), outlier.shape = NA,
alpha = 0.3, width = .1, colour = "BLACK") +
scale_y_continuous(limits=c(0.2,0.6)) + coord_flip() +
ylab('FA') + xlab('connection') + theme_cowplot() +
guides(fill = FALSE, colour = FALSE) +
theme(axis.title.x = element_text(face = "italic"))Fig 1: showing densities, data points and boxplots for the FA tracts of interest
As you can see, RSMA_RPut, RSMA_RCN, RIFJ_RCN, RDLPFC_RCN, LSMA_Lut, LSMA_LCN all appear to have one outlier. We will identify which subjects are outliers according to a more formal classification - i.e. those subjects that have a z-score greater than 3.29 on any measure (as recommended by Tabachnick & Fidell, 4th Ed, p 68).
outliers <- s1.data %>% group_by(tract_name) %>%
filter(((FA - mean(FA))/sd(FA)) > 3.29)
outliersAccording to this criteria, only subject 150 meets this criteria, for one tract (RIFJ -> RCN). We make a note of this, and will decide whether or not to exclude this subject in accordance with other criteria which we define below.
Now we will test for 2 assumptions made in our factor analysis, that of linearity and heteroscedasticity
Linearity assumes that the relationship between our variables can be described by a straight line. This is important because Pearson’s r, which forms the basis of our analysis, cannot detect non-linear relationships (i.e. curved or U-shaped, as opposed to straight lines).
We will assess linearity by visually inspecting scatterplots of each pair of our variables. To use the function that will allow me to do this, you can see in the code that I also have to convert the data from long format to wide format.
# use tidyverse functionality to convert from long to wide, drop people who have an NA value on some measure
s1.dat.wide <- s1.data %>% select(-c(group, session, tract_start, tract_end)) %>%
pivot_wider(id_cols=sub, names_from=tract_name, values_from=FA) %>%
drop_na()
# apply the pairs() function to my new dataframe - see https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/pairs for function documentation
s1.dat.wide %>% select(-sub) %>% pairs()Fig 2. Showing bivariate correlations between each pair of variables
As you can see, there are no obvious departures from there being a (varying in strength) linear relationship between the variables - or at least, there are no relationships between variables that could not be approximated with a straight line.
Heteroscedasticity assumes, in our case, where we have grouped variables (i.e. each tract is a group), that the variance across all our tracts is approximately comparable.
One easy way to assess whether our data meets this assumption is to check the ratio of the largest relative to the smallest variances in our dataset (see Tabachnick & Fiddell, p. 80). Ideally, we want to make sure that we have ratio values no greater than 10.
# get the variance of each tract
vars <- s1.data %>% select(c(tract_name, FA)) %>%
group_by(tract_name) %>%
summarise(Var=var(FA))
# divide the largest by the smallest
sprintf("ratio of largest to smallest variances: %f", max(vars$Var)/min(vars$Var))## [1] "ratio of largest to smallest variances: 2.426878"
Our value is nice and low, so we can proceed happily :)
## Normality
Now we want to check that our data are normally distributed, or normally distributed enough, for our analysis. It is more rare than you would think (at least in psychology) that we would find perfectly normally distributed variables. We largely want to make sure that there is nothing here that appears to be a gross violation of the assumption of normality.
The easiest way to check for normaility is with a qqplot. A qqplot plots the quantiles of your distribution (i.e. the point where 10% of your data lies, 20% and so on) along the y-axis, and the quantiles of a theoretical normal distribution on the x-axis. If your distribution is normal, it should form a diagonal line along the plot. If we lay our wishful diagonal line over the data, we can see how far our data deviates from this line.
qqp <- ggplot(s1.data, aes(sample=sqrt(FA))) +
stat_qq() + stat_qq_line() + facet_wrap(.~tract_name)
qqpFig 3: QQPlots for our variables of interest
This is super nice! For the first time in my history of data analysis, I see no major violations of normality that would cause me worry here. There are a couple of points that are away from the line, but nothing so consistent where a transformation could benefit the distribution’s spread.
## Check for multivariate outliers
Whereas a univariate outlier is an extreme or odd score on one variable, a multivariate outlier is an extreme score on multiple variables, for example, does one subject have unusual values across all, or a subset of the tracts?
To check this assumption, we compute the Mahalanobis distance. The Mahalanobis distance is as follows: imagine if you were plotting a figure that had as many axes as you have variables, so in this case, instead of the usual 2 axes (x & y), we would have a figure with 16 axes (very difficult to plot!). Now, imagine that 1 person is one point in this 16 dimensional plot (where their point lands corresponds to their score on each of the 16 axes). The Mahalanobis distance is just how far each person’s score would be from the average (or central) point in this 16 dimensional space. We want to make sure that no Mahalanobis score is significantly different from the rest of the pack.
mhl.mat <- as.matrix(s1.dat.wide[,2:length(colnames(s1.dat.wide))]) # here I have just turned the data into a matrix so that the subsequent functions I call can work with it
mhl.cov <- cov(mhl.mat) # here I get the covariance matrix
mhl.dist <- mahalanobis(mhl.mat, colMeans(mhl.mat), mhl.cov) # now calc the M dist
hist(mhl.dist, breaks = 20, col=wes_palette("IsleofDogs1")[1])Fig 4: histogram of Mahalanobis distance scores
The only value that really looks like it could be concerning is the one up at 30. However, we would like a more formal test to see whether we should be concerned about this value (and the rest), by asking what is the probability of getting each of our Mahalanobis distance scores by chance? If any of them have a super low probability, i.e. are less that .1 % likely (p< .001), we will classify them as a multivariate outliers. Luckily we can use the chi square distribution as a model of the distance scores that we can expect to get by chance, so we just ask, what value would a distance score need to be greater than, to have less than a .1% chance of occuring, given our current degrees of freedom? (where our degrees of freedom is n-1).
sprintf("For a Mahalanobis to be less that .1 per cent likely to have occured by chance, given our degrees of feedom (%f), it has to be a value greater than %f", length(mhl.dist)-1, qchisq(.001, df=length(mhl.dist)-1))## [1] "For a Mahalanobis to be less that .1 per cent likely to have occured by chance, given our degrees of feedom (79.000000), it has to be a value greater than 45.764222"
Given that none of our values are greater than this value, we can keep all our datapoints, including the data from participant 150, who scored as an outlier on a single variable. This is great - we want to keep as much data as we can!
## Multicollinearity and singularity Now we know we have nice, clean data inputs, we have one more thing to check before we move onto our factor analysis.
We want to make sure that our variables are correlated with one another, but not too little, nor too much. Kind of baby bear style.
We have a multicollinearity if 2 of our variables are supremely highly correlated (say, to an r value of > .9). If you think about it, it makes sense that we wouldn’t want this happening our factor analysis. For example, imagine that for one variable I record your height, and for the other, I record the highest point on which you can touch the wall. You can see how these two variables are measuring basically the same thing (how high you are, give or take some differences in arm span). When this happens, the second variable adds nothing new to your data, so its redundant to keep it in.
We have a singularity when one variable is a perfect predictor of another. Imagine I recorded your age in years, and then I counted how many birthdays you have had. These are the same thing. Again, you can see why this adds redundancy to your data.
So when testing this assumption, we want to check that all our correlations between variables are |r| < .9. First, we’ll take a look at our correlation matrix.
cor.mat <- cor(mhl.mat)
cor.plt <- ggcorrplot(cor.mat,
hc.order = FALSE,
type = "upper",
outline.color = "white",
ggtheme = ggplot2::theme_gray,
colors = c("#6D9EC1", "white", "#E46726")
)
cor.pltCorrelation matrix for our tract variables
As you can see, this looks promising. None of our correlation strengths really appear to be in the super red or blue zone. We can also check this more formally. To do this, we’ll get R to tell us whether its true or false that the absolute value in each cell is above .9 (remember that the diagonal reflects how much a variable correlates with itself, and so it should always be true - i.e. 1)
abs(cor.mat) > .9## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## LDLPFC_LCN TRUE FALSE FALSE FALSE FALSE FALSE
## LIFJ_LCN FALSE TRUE FALSE FALSE FALSE FALSE
## LSMA_LCN FALSE FALSE TRUE FALSE FALSE FALSE
## LIPL_LCN FALSE FALSE FALSE TRUE FALSE FALSE
## LDLPFC_LPut FALSE FALSE FALSE FALSE TRUE FALSE
## LIFJ_LPut FALSE FALSE FALSE FALSE FALSE TRUE
## LSMA_LPut FALSE FALSE FALSE FALSE FALSE FALSE
## LIPL_LPut FALSE FALSE FALSE FALSE FALSE FALSE
## RDLPFC_RCN FALSE FALSE FALSE FALSE FALSE FALSE
## RIFJ_RCN FALSE FALSE FALSE FALSE FALSE FALSE
## RSMA_RCN FALSE FALSE FALSE FALSE FALSE FALSE
## RIPL_RCN FALSE FALSE FALSE FALSE FALSE FALSE
## RDLPFC_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RIFJ_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RSMA_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RIPL_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## LDLPFC_LCN FALSE FALSE FALSE FALSE FALSE FALSE
## LIFJ_LCN FALSE FALSE FALSE FALSE FALSE FALSE
## LSMA_LCN FALSE FALSE FALSE FALSE FALSE FALSE
## LIPL_LCN FALSE FALSE FALSE FALSE FALSE FALSE
## LDLPFC_LPut FALSE FALSE FALSE FALSE FALSE FALSE
## LIFJ_LPut FALSE FALSE FALSE FALSE FALSE FALSE
## LSMA_LPut TRUE FALSE FALSE FALSE FALSE FALSE
## LIPL_LPut FALSE TRUE FALSE FALSE FALSE FALSE
## RDLPFC_RCN FALSE FALSE TRUE FALSE FALSE FALSE
## RIFJ_RCN FALSE FALSE FALSE TRUE FALSE FALSE
## RSMA_RCN FALSE FALSE FALSE FALSE TRUE FALSE
## RIPL_RCN FALSE FALSE FALSE FALSE FALSE TRUE
## RDLPFC_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RIFJ_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RSMA_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RIPL_RPut FALSE FALSE FALSE FALSE FALSE FALSE
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## LDLPFC_LCN FALSE FALSE FALSE FALSE
## LIFJ_LCN FALSE FALSE FALSE FALSE
## LSMA_LCN FALSE FALSE FALSE FALSE
## LIPL_LCN FALSE FALSE FALSE FALSE
## LDLPFC_LPut FALSE FALSE FALSE FALSE
## LIFJ_LPut FALSE FALSE FALSE FALSE
## LSMA_LPut FALSE FALSE FALSE FALSE
## LIPL_LPut FALSE FALSE FALSE FALSE
## RDLPFC_RCN FALSE FALSE FALSE FALSE
## RIFJ_RCN FALSE FALSE FALSE FALSE
## RSMA_RCN FALSE FALSE FALSE FALSE
## RIPL_RCN FALSE FALSE FALSE FALSE
## RDLPFC_RPut TRUE FALSE FALSE FALSE
## RIFJ_RPut FALSE TRUE FALSE FALSE
## RSMA_RPut FALSE FALSE TRUE FALSE
## RIPL_RPut FALSE FALSE FALSE TRUE
As you can see, we have no multicollinearity or singularity, so we are good to proceed with our factor analysis!
## Exploratory Factor Analysis
The following is how I think of a factor analysis: At the moment, I have 16 tracts/variables. As I mentioned above, one way to represent this is to create a figure with 16 axes, where each point in this new 16 dimensional space reflects one participant’s score on all 16 variables. Usually, in a 2-dimensional figure, where there is only an x-axis and a y-axis, the location of a datapoint d can be given by a vector containing 2 elements, 1 for the position on the x-axis and 1 for the position on the y axis: d = [x, y]. In the 16 dimensional space, the position of a datapoint would be given by a vector containing 16 datapoints d = [v1, v2, ...v16]. However, 16 is a high number of axes to use, to give the position of one datapoint (or each of our datapoints). In a factor analysis, what we are essentially asking is: what is the smallest number of axes (aka factors) I can use and still describe my data? So really, a factor is an axes along which you can plot your data, and from a factor analysis you get a lower number of axes/factors to represent your data than you had originally.
To learn the smallest number of factors we can use to represent our data, we seek to reproduce our observed correlation matrix (that we plotted above), using eigenvalues and eigenvectors. You can think of eigenvectors as the new axes in your reduced multidimensional figure. When you plot something in 2D using the standard Cartesian coordinates you are essentially using eigenvectors. The eigenvalue tells you how long your eigenvector (aka axis) should be to describe all the datapoints along that dimension. The larger the eigenvalue, the longer that axis has to be, meaning that the eigenvector has to be stretched out along the direction it points in to draw a line through all the datapoints (and thus give them a coordinate on that axis). This is good, because it tells you that there is a lot of variance in the direction that the eigenvector points. This means we are explaining lots of variance, which is what we want to do! Small eigenvalues mean that the corresponding eigenvector is going to be pretty small, meaning that an axis in that direction does not account for a lot of variance in the data.
Although the calculations to find eigenvalues and eigenvectors can be somewhat cumbersome (see Appendix A of Tabachnik & Fidell, 4th Ed for an example), actually performaing a factor analysis in R is relatively simple. The first challenge though, is to determine how many factors we want to keep. There are multiple methods to determine this:
- Run a parallel analysis
Generate a random dataset the same size as your own, that has no factors underlying the data (because its random). Compute the eigenvalues you get with random data. Repeat this over 1000 iterations. This gives you a distribution of which eigenvalues you would get by chance. You then ask which of your own eigenvalues are higher than those that occur by chance over 95% of the time (i.e. those which are unlikely to have occurred by chance). See the green ‘parallel analysis’ line in the figure below.
- Look at the accelaration factor (AF)
The accelaration factor indicates where the elbow of the scree plot (the plot of eigenvalues sorted in order of size) is. It corresponds to the accelaration of the line drawn by connecting the eigenvalues of the scree plot (see the blue values in the Figure below).
- The optimal coordinates (OC)
Basically, searching for optimal coordinates involves performing a linear regression, where the value of the current eigenvalue is predicted using the value of the previous eigenvalue. If the current eigenvalue can be predicted by the previous value, it sits on the regression line (see the red line in the figure below). Eigenvalues that explain unique variance should be above the red regression line.
ev <- eigen(cor.mat) # get the eigenvalues using the correlation matrix
ap <- parallel(subject=nrow(mhl.mat), var=ncol(mhl.mat), rep=1000, quantile=.05, model="factors") # run the parallel analysis
nS <- nScree(x=ev$values, aparallel=ap$eigen$qevpea, criteria=0) # calculate the 95% values for the parallel analysis, plus the accelaration factor and the optimal coordinates
plotnScree(nS, xlab="Eigenvalues")Scree plot with factor number decision tools
As you can see from the parallel analysis and the accelaration factor, we have reasonably strong reasons to think that we can sufficiently explain our data with 2 factors. Given the AF and the OC run between 2 and 6, I will explore the models with 2-6 factors, to see which provide a more sensible account of the data.
For each model I will examine 3 pieces of information that will help me determine which solution provides the most sensible model of the data: the Sum of Square loadings, a test of the null hypothesis that the number of factors in our model is sufficient to explain the data, and the meaning given from factor rotations.
Lets now run the factor analysis. I will print out the results from the first so that you can get a feel for the output.
factors = c(2,3,4,5,6)
factor_models <- lapply(factors, function(x) factanal(mhl.mat, factors=x)) # run factor analysis with 2, 3, or 4 factors, save output of each to factor_models
factor_models[[1]]##
## Call:
## factanal(x = mhl.mat, factors = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.284 0.536 0.271 0.572 0.185 0.604
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.239 0.522 0.252 0.434 0.347 0.693
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.102 0.634 0.236 0.617
##
## Loadings:
## Factor1 Factor2
## LDLPFC_LCN 0.348 0.771
## LIFJ_LCN 0.443 0.518
## LSMA_LCN 0.333 0.787
## LIPL_LCN 0.502 0.420
## LDLPFC_LPut 0.741 0.515
## LIFJ_LPut 0.549 0.308
## LSMA_LPut 0.811 0.320
## LIPL_LPut 0.598 0.346
## RDLPFC_RCN 0.385 0.775
## RIFJ_RCN 0.217 0.720
## RSMA_RCN 0.334 0.736
## RIPL_RCN 0.359 0.421
## RDLPFC_RPut 0.838 0.443
## RIFJ_RPut 0.500 0.341
## RSMA_RPut 0.855 0.183
## RIPL_RPut 0.572 0.236
##
## Factor1 Factor2
## SS loadings 4.991 4.480
## Proportion Var 0.312 0.280
## Cumulative Var 0.312 0.592
##
## Test of the hypothesis that 2 factors are sufficient.
## The chi square statistic is 224.05 on 89 degrees of freedom.
## The p-value is 1.26e-13
Sum of Square (SS) loadings
The sum of squared loadings essentially squares how much each variable loads onto a given factor, and then sums those loadings. The higher this sum, the more that factor captures the variance across variables. Here we can apply Kaiser’s rule which states that a factor is worth keeping if the SS > 1.
Lets print out the SS loadings for each model and compare them:
lapply(factors, function(x) factor_models[[x-1]]$loadings)## [[1]]
##
## Loadings:
## Factor1 Factor2
## LDLPFC_LCN 0.348 0.771
## LIFJ_LCN 0.443 0.518
## LSMA_LCN 0.333 0.787
## LIPL_LCN 0.502 0.420
## LDLPFC_LPut 0.741 0.515
## LIFJ_LPut 0.549 0.308
## LSMA_LPut 0.811 0.320
## LIPL_LPut 0.598 0.346
## RDLPFC_RCN 0.385 0.775
## RIFJ_RCN 0.217 0.720
## RSMA_RCN 0.334 0.736
## RIPL_RCN 0.359 0.421
## RDLPFC_RPut 0.838 0.443
## RIFJ_RPut 0.500 0.341
## RSMA_RPut 0.855 0.183
## RIPL_RPut 0.572 0.236
##
## Factor1 Factor2
## SS loadings 4.991 4.480
## Proportion Var 0.312 0.280
## Cumulative Var 0.312 0.592
##
## [[2]]
##
## Loadings:
## Factor1 Factor2 Factor3
## LDLPFC_LCN 0.604 0.616
## LIFJ_LCN 0.576 0.365 0.191
## LSMA_LCN 0.305 0.771 0.259
## LIPL_LCN 0.522 0.317 0.265
## LDLPFC_LPut 0.744 0.371 0.421
## LIFJ_LPut 0.488 0.245 0.322
## LSMA_LPut 0.450 0.311 0.686
## LIPL_LPut 0.600 0.233 0.315
## RDLPFC_RCN 0.415 0.735 0.225
## RIFJ_RCN 0.369 0.634
## RSMA_RCN 0.113 0.861 0.359
## RIPL_RCN 0.334 0.365 0.243
## RDLPFC_RPut 0.654 0.334 0.604
## RIFJ_RPut 0.394 0.271 0.365
## RSMA_RPut 0.281 0.192 0.933
## RIPL_RPut 0.471 0.171 0.356
##
## Factor1 Factor2 Factor3
## SS loadings 3.732 3.624 2.772
## Proportion Var 0.233 0.226 0.173
## Cumulative Var 0.233 0.460 0.633
##
## [[3]]
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4
## LDLPFC_LCN 0.584 0.573 0.278
## LIFJ_LCN 0.350 0.608 0.219
## LSMA_LCN 0.763 0.303 0.244 0.162
## LIPL_LCN 0.294 0.397 0.233 0.402
## LDLPFC_LPut 0.341 0.689 0.420 0.340
## LIFJ_LPut 0.224 0.459 0.322 0.215
## LSMA_LPut 0.300 0.378 0.670 0.297
## LIPL_LPut 0.196 0.410 0.258 0.569
## RDLPFC_RCN 0.719 0.382 0.207 0.238
## RIFJ_RCN 0.620 0.359 0.170
## RSMA_RCN 0.856 0.324 0.183
## RIPL_RCN 0.347 0.158 0.181 0.468
## RDLPFC_RPut 0.315 0.562 0.594 0.363
## RIFJ_RPut 0.252 0.261 0.324 0.397
## RSMA_RPut 0.198 0.189 0.919 0.268
## RIPL_RPut 0.109 0.109 0.213 0.962
##
## Factor1 Factor2 Factor3 Factor4
## SS loadings 3.394 2.685 2.497 2.474
## Proportion Var 0.212 0.168 0.156 0.155
## Cumulative Var 0.212 0.380 0.536 0.691
##
## [[4]]
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4 Factor5
## LDLPFC_LCN 0.552 0.148 0.277 0.232 0.664
## LIFJ_LCN 0.271 0.243 0.701 0.233
## LSMA_LCN 0.737 0.267 0.260 0.142 0.240
## LIPL_LCN 0.244 0.258 0.462 0.393 0.144
## LDLPFC_LPut 0.301 0.540 0.435 0.295 0.465
## LIFJ_LPut 0.180 0.377 0.508 0.203
## LSMA_LPut 0.291 0.741 0.262 0.265 0.150
## LIPL_LPut 0.157 0.307 0.403 0.556 0.177
## RDLPFC_RCN 0.685 0.271 0.263 0.211 0.313
## RIFJ_RCN 0.574 0.551 0.175 0.113
## RSMA_RCN 0.868 0.308 0.158 0.177
## RIPL_RCN 0.328 0.173 0.196 0.465
## RDLPFC_RPut 0.284 0.684 0.368 0.324 0.336
## RIFJ_RPut 0.218 0.307 0.428 0.401
## RSMA_RPut 0.222 0.871 0.166 0.256
## RIPL_RPut 0.105 0.250 0.951 0.112
##
## Factor1 Factor2 Factor3 Factor4 Factor5
## SS loadings 3.062 2.879 2.314 2.301 1.097
## Proportion Var 0.191 0.180 0.145 0.144 0.069
## Cumulative Var 0.191 0.371 0.516 0.660 0.728
##
## [[5]]
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## LDLPFC_LCN 0.153 0.482 0.280 0.225 0.769
## LIFJ_LCN 0.251 0.238 0.703 0.244
## LSMA_LCN 0.297 0.689 0.284 0.135 0.308
## LIPL_LCN 0.274 0.215 0.469 0.393 0.159
## LDLPFC_LPut 0.554 0.262 0.440 0.299 0.446
## LIFJ_LPut 0.377 0.180 0.511 0.209
## LSMA_LPut 0.820 0.262 0.268 0.248 0.159 -0.162
## LIPL_LPut 0.307 0.139 0.411 0.560 0.167
## RDLPFC_RCN 0.252 0.674 0.261 0.224 0.320 0.270
## RIFJ_RCN 0.538 0.565 0.180 0.180
## RSMA_RCN 0.294 0.880 0.175 0.180
## RIPL_RCN 0.146 0.319 0.202 0.474 0.115
## RDLPFC_RPut 0.681 0.258 0.356 0.336 0.313 0.357
## RIFJ_RPut 0.268 0.214 0.421 0.416 0.161
## RSMA_RPut 0.813 0.236 0.172 0.272 0.112
## RIPL_RPut 0.249 0.951 0.120
##
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## SS loadings 2.896 2.799 2.366 2.344 1.292 0.282
## Proportion Var 0.181 0.175 0.148 0.146 0.081 0.018
## Cumulative Var 0.181 0.356 0.504 0.650 0.731 0.749
As you can see, for the 6 factor model, we find that the 6th factor has an SS value of < 1, which suggests that we can drop it from consideration of our potential solutions.
Testing the null hypothesis that we have sufficient factors in our model to explain the data
Next we use a chi square test to determine whether our model contains sufficient factors to explain the variance in our data. If we have a p-value that suggests a significant result, then our null hypothesis is rejected and we assume that we don’t have enough factors in our model to capture the full dimensionality of our dataset. As we are running 6 tests (one for each factor analysis), we can adjust our p-value accordingly. Here I’ll use Bonferroni and assess significance at p< .05/6 = .008.
lapply(factors, function(x) factor_models[[x-1]]$PVAL < .008)## [[1]]
## objective
## TRUE
##
## [[2]]
## objective
## TRUE
##
## [[3]]
## objective
## TRUE
##
## [[4]]
## objective
## TRUE
##
## [[5]]
## objective
## FALSE
This shows that we may need the 6 factor model to capture the dimensionality of our data. Given the mixed information provided by these two criteria, it makes sense to explore the factor loadings, with and without rotations, to see which factor analysis model provides the most sensible account of the data. I will try both Varimax (orthogonal) and Promax (oblique) rotations.
Two factor solution
rotations = c("varimax", "promax")
lapply(rotations, function(x) factanal(mhl.mat, factors=2, rotation=x))## [[1]]
##
## Call:
## factanal(x = mhl.mat, factors = 2, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.284 0.536 0.271 0.572 0.185 0.604
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.239 0.522 0.252 0.434 0.347 0.693
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.102 0.634 0.236 0.617
##
## Loadings:
## Factor1 Factor2
## LDLPFC_LCN 0.348 0.771
## LIFJ_LCN 0.443 0.518
## LSMA_LCN 0.333 0.787
## LIPL_LCN 0.502 0.420
## LDLPFC_LPut 0.741 0.515
## LIFJ_LPut 0.549 0.308
## LSMA_LPut 0.811 0.320
## LIPL_LPut 0.598 0.346
## RDLPFC_RCN 0.385 0.775
## RIFJ_RCN 0.217 0.720
## RSMA_RCN 0.334 0.736
## RIPL_RCN 0.359 0.421
## RDLPFC_RPut 0.838 0.443
## RIFJ_RPut 0.500 0.341
## RSMA_RPut 0.855 0.183
## RIPL_RPut 0.572 0.236
##
## Factor1 Factor2
## SS loadings 4.991 4.480
## Proportion Var 0.312 0.280
## Cumulative Var 0.312 0.592
##
## Test of the hypothesis that 2 factors are sufficient.
## The chi square statistic is 224.05 on 89 degrees of freedom.
## The p-value is 1.26e-13
##
## [[2]]
##
## Call:
## factanal(x = mhl.mat, factors = 2, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.284 0.536 0.271 0.572 0.185 0.604
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.239 0.522 0.252 0.434 0.347 0.693
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.102 0.634 0.236 0.617
##
## Loadings:
## Factor1 Factor2
## LDLPFC_LCN 0.863
## LIFJ_LCN 0.274 0.450
## LSMA_LCN 0.894
## LIPL_LCN 0.418 0.279
## LDLPFC_LPut 0.686 0.265
## LIFJ_LPut 0.556
## LSMA_LPut 0.910
## LIPL_LPut 0.600 0.115
## RDLPFC_RCN 0.845
## RIFJ_RCN -0.169 0.872
## RSMA_RCN 0.823
## RIPL_RCN 0.221 0.367
## RDLPFC_RPut 0.867 0.104
## RIFJ_RPut 0.467 0.169
## RSMA_RPut 1.059 -0.269
## RIPL_RPut 0.635
##
## Factor1 Factor2
## SS loadings 4.792 4.318
## Proportion Var 0.300 0.270
## Cumulative Var 0.300 0.569
##
## Factor Correlations:
## Factor1 Factor2
## Factor1 1.000 0.755
## Factor2 0.755 1.000
##
## Test of the hypothesis that 2 factors are sufficient.
## The chi square statistic is 224.05 on 89 degrees of freedom.
## The p-value is 1.26e-13
This solution is actually pretty nice, given that factors divide into whether the cortical tract projects to the putamen or to the caudate. The promax rotation appears to reflect this interpretation.
Three factor solution
lapply(rotations, function(x) factanal(mhl.mat, factors=3, rotation=x))## [[1]]
##
## Call:
## factanal(x = mhl.mat, factors = 3, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.250 0.498 0.246 0.557 0.131 0.598
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.231 0.487 0.236 0.455 0.118 0.696
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.097 0.638 0.013 0.623
##
## Loadings:
## Factor1 Factor2 Factor3
## LDLPFC_LCN 0.604 0.616
## LIFJ_LCN 0.576 0.365 0.191
## LSMA_LCN 0.305 0.771 0.259
## LIPL_LCN 0.522 0.317 0.265
## LDLPFC_LPut 0.744 0.371 0.421
## LIFJ_LPut 0.488 0.245 0.322
## LSMA_LPut 0.450 0.311 0.686
## LIPL_LPut 0.600 0.233 0.315
## RDLPFC_RCN 0.415 0.735 0.225
## RIFJ_RCN 0.369 0.634
## RSMA_RCN 0.113 0.861 0.359
## RIPL_RCN 0.334 0.365 0.243
## RDLPFC_RPut 0.654 0.334 0.604
## RIFJ_RPut 0.394 0.271 0.365
## RSMA_RPut 0.281 0.192 0.933
## RIPL_RPut 0.471 0.171 0.356
##
## Factor1 Factor2 Factor3
## SS loadings 3.732 3.624 2.772
## Proportion Var 0.233 0.226 0.173
## Cumulative Var 0.233 0.460 0.633
##
## Test of the hypothesis that 3 factors are sufficient.
## The chi square statistic is 154.93 on 75 degrees of freedom.
## The p-value is 1.68e-07
##
## [[2]]
##
## Call:
## factanal(x = mhl.mat, factors = 3, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.250 0.498 0.246 0.557 0.131 0.598
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.231 0.487 0.236 0.455 0.118 0.696
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.097 0.638 0.013 0.623
##
## Loadings:
## Factor1 Factor2 Factor3
## LDLPFC_LCN 0.689 0.362 -0.276
## LIFJ_LCN 0.715
## LSMA_LCN 0.785
## LIPL_LCN 0.625
## LDLPFC_LPut 0.911
## LIFJ_LPut 0.583 0.107
## LSMA_LPut 0.378 0.102 0.531
## LIPL_LPut 0.770 -0.121
## RDLPFC_RCN 0.289 0.658
## RIFJ_RCN 0.301 0.556 -0.168
## RSMA_RCN -0.294 1.044 0.234
## RIPL_RCN 0.308 0.240
## RDLPFC_RPut 0.723 0.340
## RIFJ_RPut 0.406 0.196
## RSMA_RPut 0.910
## RIPL_RPut 0.575 -0.106 0.165
##
## Factor1 Factor2 Factor3
## SS loadings 4.667 2.696 1.490
## Proportion Var 0.292 0.168 0.093
## Cumulative Var 0.292 0.460 0.553
##
## Factor Correlations:
## Factor1 Factor2 Factor3
## Factor1 1.000 0.375 0.587
## Factor2 0.375 1.000 0.735
## Factor3 0.587 0.735 1.000
##
## Test of the hypothesis that 3 factors are sufficient.
## The chi square statistic is 154.93 on 75 degrees of freedom.
## The p-value is 1.68e-07
This solution appears a little messier for interpretability. SMA appears to load onto a distinct factor with regards as to whether it projects to the caudate or the putamen. There also appear to be left and right lateralised networks emerging.
Four factor solution
lapply(rotations, function(x) factanal(mhl.mat, factors=4, rotation=x))## [[1]]
##
## Call:
## factanal(x = mhl.mat, factors = 4, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.247 0.450 0.241 0.540 0.118 0.589
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.229 0.402 0.238 0.453 0.121 0.602
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.100 0.606 0.009 0.005
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4
## LDLPFC_LCN 0.584 0.573 0.278
## LIFJ_LCN 0.350 0.608 0.219
## LSMA_LCN 0.763 0.303 0.244 0.162
## LIPL_LCN 0.294 0.397 0.233 0.402
## LDLPFC_LPut 0.341 0.689 0.420 0.340
## LIFJ_LPut 0.224 0.459 0.322 0.215
## LSMA_LPut 0.300 0.378 0.670 0.297
## LIPL_LPut 0.196 0.410 0.258 0.569
## RDLPFC_RCN 0.719 0.382 0.207 0.238
## RIFJ_RCN 0.620 0.359 0.170
## RSMA_RCN 0.856 0.324 0.183
## RIPL_RCN 0.347 0.158 0.181 0.468
## RDLPFC_RPut 0.315 0.562 0.594 0.363
## RIFJ_RPut 0.252 0.261 0.324 0.397
## RSMA_RPut 0.198 0.189 0.919 0.268
## RIPL_RPut 0.109 0.109 0.213 0.962
##
## Factor1 Factor2 Factor3 Factor4
## SS loadings 3.394 2.685 2.497 2.474
## Proportion Var 0.212 0.168 0.156 0.155
## Cumulative Var 0.212 0.380 0.536 0.691
##
## Test of the hypothesis that 4 factors are sufficient.
## The chi square statistic is 113.31 on 62 degrees of freedom.
## The p-value is 7.59e-05
##
## [[2]]
##
## Call:
## factanal(x = mhl.mat, factors = 4, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.247 0.450 0.241 0.540 0.118 0.589
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.229 0.402 0.238 0.453 0.121 0.602
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.100 0.606 0.009 0.005
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4
## LDLPFC_LCN 0.705 0.339 -0.270
## LIFJ_LCN 0.889 -0.250
## LSMA_LCN 0.145 0.789
## LIPL_LCN 0.434 0.255
## LDLPFC_LPut 0.925 0.130
## LIFJ_LPut 0.614 0.142
## LSMA_LPut 0.345 0.568
## LIPL_LPut 0.441 -0.114 0.482
## RDLPFC_RCN 0.290 0.662
## RIFJ_RCN 0.334 0.555 -0.165
## RSMA_RCN -0.300 1.062 0.207
## RIPL_RCN 0.284 0.456
## RDLPFC_RPut 0.666 0.389
## RIFJ_RPut 0.188 0.288 0.169
## RSMA_RPut 0.964
## RIPL_RPut -0.180 1.167
##
## Factor1 Factor2 Factor3 Factor4
## SS loadings 3.841 2.752 2.028 1.617
## Proportion Var 0.240 0.172 0.127 0.101
## Cumulative Var 0.240 0.412 0.539 0.640
##
## Factor Correlations:
## Factor1 Factor2 Factor3 Factor4
## Factor1 1.000 -0.578 0.541 0.698
## Factor2 -0.578 1.000 -0.431 -0.607
## Factor3 0.541 -0.431 1.000 0.756
## Factor4 0.698 -0.607 0.756 1.000
##
## Test of the hypothesis that 4 factors are sufficient.
## The chi square statistic is 113.31 on 62 degrees of freedom.
## The p-value is 7.59e-05
This is kind of interesting in that again, projections from SMA to Caudate Nucleus and Putamen appear to load onto their own factors (factors 2 & 4), with a few other select cortical regions. Factor 1 appears to reflect pre-frontal projections to caudate and putamen. Factor 3 reflects IPL and RIFJ connectivity to caudate and putamen.
Five factor solution
lapply(rotations, function(x) factanal(mhl.mat, factors=5, rotation=x))## [[1]]
##
## Call:
## factanal(x = mhl.mat, factors = 5, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.101 0.314 0.240 0.486 0.126 0.519
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.205 0.378 0.246 0.322 0.095 0.599
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.098 0.514 0.099 0.005
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4 Factor5
## LDLPFC_LCN 0.552 0.148 0.277 0.232 0.664
## LIFJ_LCN 0.271 0.243 0.701 0.233
## LSMA_LCN 0.737 0.267 0.260 0.142 0.240
## LIPL_LCN 0.244 0.258 0.462 0.393 0.144
## LDLPFC_LPut 0.301 0.540 0.435 0.295 0.465
## LIFJ_LPut 0.180 0.377 0.508 0.203
## LSMA_LPut 0.291 0.741 0.262 0.265 0.150
## LIPL_LPut 0.157 0.307 0.403 0.556 0.177
## RDLPFC_RCN 0.685 0.271 0.263 0.211 0.313
## RIFJ_RCN 0.574 0.551 0.175 0.113
## RSMA_RCN 0.868 0.308 0.158 0.177
## RIPL_RCN 0.328 0.173 0.196 0.465
## RDLPFC_RPut 0.284 0.684 0.368 0.324 0.336
## RIFJ_RPut 0.218 0.307 0.428 0.401
## RSMA_RPut 0.222 0.871 0.166 0.256
## RIPL_RPut 0.105 0.250 0.951 0.112
##
## Factor1 Factor2 Factor3 Factor4 Factor5
## SS loadings 3.062 2.879 2.314 2.301 1.097
## Proportion Var 0.191 0.180 0.145 0.144 0.069
## Cumulative Var 0.191 0.371 0.516 0.660 0.728
##
## Test of the hypothesis that 5 factors are sufficient.
## The chi square statistic is 82.19 on 50 degrees of freedom.
## The p-value is 0.00278
##
## [[2]]
##
## Call:
## factanal(x = mhl.mat, factors = 5, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.101 0.314 0.240 0.486 0.126 0.519
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.205 0.378 0.246 0.322 0.095 0.599
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.098 0.514 0.099 0.005
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4 Factor5
## LDLPFC_LCN -0.168 0.248 0.771
## LIFJ_LCN 1.038 -0.313
## LSMA_LCN 0.682 0.195
## LIPL_LCN 0.524 0.229
## LDLPFC_LPut 0.337 0.380 0.411
## LIFJ_LPut 0.666 0.237
## LSMA_LPut 0.798 0.111
## LIPL_LPut 0.368 0.480 -0.122
## RDLPFC_RCN 0.576 0.289
## RIFJ_RCN 0.739 -0.321 0.433
## RSMA_RCN -0.121 0.196 0.991
## RIPL_RCN 0.468 0.233
## RDLPFC_RPut 0.194 0.625 0.236
## RIFJ_RPut 0.488 0.119 0.245 -0.218
## RSMA_RPut -0.120 1.057 0.122 -0.178
## RIPL_RPut -0.324 1.214
##
## Factor1 Factor2 Factor3 Factor4 Factor5
## SS loadings 3.019 2.547 2.170 2.147 1.052
## Proportion Var 0.189 0.159 0.136 0.134 0.066
## Cumulative Var 0.189 0.348 0.484 0.618 0.683
##
## Factor Correlations:
## Factor1 Factor2 Factor3 Factor4 Factor5
## Factor1 1.000 0.509 0.658 0.466 0.722
## Factor2 0.509 1.000 0.517 0.585 0.675
## Factor3 0.658 0.517 1.000 0.543 0.716
## Factor4 0.466 0.585 0.543 1.000 0.639
## Factor5 0.722 0.675 0.716 0.639 1.000
##
## Test of the hypothesis that 5 factors are sufficient.
## The chi square statistic is 82.19 on 50 degrees of freedom.
## The p-value is 0.00278
Factor 1 = IFJ (dominant) to CN and putamen, Factor 2 = SMA (dominant) to putamen, with some IFJ to putamen and not to caudate. Factor 3 = Parietal to caudate and putamen, Factor 4 = frontal-parietal to caudate, Factor 5 = DLPFC to CN and or Put. Still seems a tad messy
Six factor solution
lapply(rotations, function(x) factanal(mhl.mat, factors=6, rotation=x))## [[1]]
##
## Call:
## factanal(x = mhl.mat, factors = 6, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.022 0.316 0.240 0.480 0.137 0.517
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.073 0.376 0.189 0.324 0.071 0.593
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.005 0.507 0.167 0.005
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## LDLPFC_LCN 0.153 0.482 0.280 0.225 0.769
## LIFJ_LCN 0.251 0.238 0.703 0.244
## LSMA_LCN 0.297 0.689 0.284 0.135 0.308
## LIPL_LCN 0.274 0.215 0.469 0.393 0.159
## LDLPFC_LPut 0.554 0.262 0.440 0.299 0.446
## LIFJ_LPut 0.377 0.180 0.511 0.209
## LSMA_LPut 0.820 0.262 0.268 0.248 0.159 -0.162
## LIPL_LPut 0.307 0.139 0.411 0.560 0.167
## RDLPFC_RCN 0.252 0.674 0.261 0.224 0.320 0.270
## RIFJ_RCN 0.538 0.565 0.180 0.180
## RSMA_RCN 0.294 0.880 0.175 0.180
## RIPL_RCN 0.146 0.319 0.202 0.474 0.115
## RDLPFC_RPut 0.681 0.258 0.356 0.336 0.313 0.357
## RIFJ_RPut 0.268 0.214 0.421 0.416 0.161
## RSMA_RPut 0.813 0.236 0.172 0.272 0.112
## RIPL_RPut 0.249 0.951 0.120
##
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## SS loadings 2.896 2.799 2.366 2.344 1.292 0.282
## Proportion Var 0.181 0.175 0.148 0.146 0.081 0.018
## Cumulative Var 0.181 0.356 0.504 0.650 0.731 0.749
##
## Test of the hypothesis that 6 factors are sufficient.
## The chi square statistic is 52.57 on 39 degrees of freedom.
## The p-value is 0.072
##
## [[2]]
##
## Call:
## factanal(x = mhl.mat, factors = 6, rotation = x)
##
## Uniquenesses:
## LDLPFC_LCN LIFJ_LCN LSMA_LCN LIPL_LCN LDLPFC_LPut LIFJ_LPut
## 0.022 0.316 0.240 0.480 0.137 0.517
## LSMA_LPut LIPL_LPut RDLPFC_RCN RIFJ_RCN RSMA_RCN RIPL_RCN
## 0.073 0.376 0.189 0.324 0.071 0.593
## RDLPFC_RPut RIFJ_RPut RSMA_RPut RIPL_RPut
## 0.005 0.507 0.167 0.005
##
## Loadings:
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## LDLPFC_LCN 0.108 0.137 0.792
## LIFJ_LCN 1.023 -0.303
## LSMA_LCN 0.126 0.635 0.148 0.212
## LIPL_LCN 0.532 0.233
## LDLPFC_LPut 0.345 -0.104 0.388 0.321 0.157
## LIFJ_LPut 0.662 0.225 -0.117
## LSMA_LPut 0.127 0.869 -0.135
## LIPL_LPut 0.386 0.491 -0.115
## RDLPFC_RCN 0.551 0.161 0.376
## RIFJ_RCN 0.748 0.389 -0.292
## RSMA_RCN 1.029 0.152
## RIPL_RCN 0.457 0.229
## RDLPFC_RPut 0.117 0.504 0.574
## RIFJ_RPut 0.443 0.216 -0.217 0.172
## RSMA_RPut -0.125 0.141 0.832 -0.177 0.247
## RIPL_RPut -0.314 1.212
##
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## SS loadings 2.962 2.150 2.069 2.055 0.922 0.628
## Proportion Var 0.185 0.134 0.129 0.128 0.058 0.039
## Cumulative Var 0.185 0.320 0.449 0.577 0.635 0.674
##
## Factor Correlations:
## Factor1 Factor2 Factor3 Factor4 Factor5 Factor6
## Factor1 1.000 0.631 -0.334 -0.501 -0.580 0.709
## Factor2 0.631 1.000 -0.437 -0.565 -0.493 0.664
## Factor3 -0.334 -0.437 1.000 0.564 0.380 -0.543
## Factor4 -0.501 -0.565 0.564 1.000 0.465 -0.678
## Factor5 -0.580 -0.493 0.380 0.465 1.000 -0.649
## Factor6 0.709 0.664 -0.543 -0.678 -0.649 1.000
##
## Test of the hypothesis that 6 factors are sufficient.
## The chi square statistic is 52.57 on 39 degrees of freedom.
## The p-value is 0.072
Again, I can probably squint some meaningful factors, but it is getting a tad nebulous
A work by Kelly Garner